"""
用户业务服务
============

处理用户相关的业务逻辑
"""

from datetime import datetime, timezone
from typing import List, Optional, Tuple
from dependency_injector.wiring import inject, Provide

from redfire_framework.core.security import JWTManager, PasswordManager
from redfire_framework.core.exceptions import (
    UserNotFoundException,
    UserAlreadyExistsException,
    InvalidCredentialsError,
    DatabaseTransactionError
)
from ..models.user import User
from ..repositories.user_repository import UserRepository
from .audit_service import AuditService
from .transaction_service import TransactionService


class UserService:
    """用户业务服务类"""
    
    @inject
    def __init__(
        self,
        user_repository: UserRepository = Provide["user_repository"],
        transaction_service: TransactionService = Provide["transaction_service"],
        jwt_manager: JWTManager = Provide["jwt_manager"],
        password_manager: PasswordManager = Provide["password_manager"],
        audit_service: AuditService = Provide["audit_service"]
    ):
        self.user_repository = user_repository
        self.transaction_service = transaction_service
        self.jwt_manager = jwt_manager
        self.password_manager = password_manager
        self.audit_service = audit_service
    
    async def create_user(
        self,
        username: str,
        email: str,
        password: str,
        full_name: Optional[str] = None,
        phone: Optional[str] = None,
        is_active: bool = True
    ) -> User:
        """
        创建用户
        
        Args:
            username: 用户名
            email: 邮箱
            password: 密码
            full_name: 全名（可选）
            phone: 电话（可选）
            is_active: 是否激活
            
        Returns:
            创建的用户对象
            
        Raises:
            ValueError: 输入数据验证失败
            UserAlreadyExistsException: 用户名或邮箱已存在
            DatabaseTransactionError: 数据库创建失败
        """
        # 验证输入数据
        if not email or "@" not in email:
            raise ValueError("Invalid email format")
        if not password or len(password) < 6:
            raise ValueError("Password must be at least 6 characters")
        if not username or len(username) < 3:
            raise ValueError("Username must be at least 3 characters")
        
        # 检查用户名是否已存在
        if await self.user_repository.exists_by_username(username):
            raise UserAlreadyExistsException(
                message=f"用户名 '{username}' 已存在",
                identifier=username
            )
        
        # 检查邮箱是否已存在
        if await self.user_repository.exists_by_email(email):
            raise UserAlreadyExistsException(
                message=f"邮箱 '{email}' 已被注册",
                identifier=email
            )
        
        # 准备数据
        hashed_password = self.password_manager.hash_password(password)
        user_data = {
            "username": username,
            "email": email,
            "password_hash": hashed_password,
            "status": "active" if is_active else "pending_verification",
            "full_name": full_name,
            "phone": phone
        }
        
        # 直接创建用户（所有信息都在 users 表中）
        try:
            user = await self.user_repository.create(user_data)
            
            # 记录审计日志
            try:
                await self.audit_service.log_user_action(
                    user_id=user.id,
                    action="user_created",
                    details={
                        "username": username, 
                        "email": email
                    }
                )
            except Exception:
                # 审计日志失败不应影响用户创建
                pass
            
            return user
            
        except Exception as e:
            # 异常包装
            raise DatabaseTransactionError(
                f"User creation failed: {str(e)}"
            ) from e
    
    async def get_user_by_id(self, user_id: str) -> Optional[User]:
        """根据ID获取用户"""
        return await self.user_repository.get_by_id(user_id)
    
    async def get_user_by_username(self, username: str) -> Optional[User]:
        """根据用户名获取用户"""
        return await self.user_repository.get_by_username(username)
    
    async def get_user_by_email(self, email: str) -> Optional[User]:
        """根据邮箱获取用户"""
        return await self.user_repository.get_by_email(email)
    
    async def authenticate_user(
        self, 
        username: str, 
        password: str
    ) -> Optional[User]:
        """验证用户凭证"""
        # 尝试用户名登录
        user = await self.get_user_by_username(username)
        if not user:
            # 尝试邮箱登录
            user = await self.get_user_by_email(username)
        
        if not user:
            await self.audit_service.log_security_event(
                event_type="login_failed",
                details={"reason": "user_not_found", "identifier": username}
            )
            return None
        
        if not user.is_active:
            await self.audit_service.log_security_event(
                event_type="login_failed",
                details={"reason": "user_inactive", "user_id": user.id}
            )
            return None
        
        if not self.password_manager.verify_password(password, user.hashed_password):
            await self.audit_service.log_security_event(
                event_type="login_failed",
                details={"reason": "invalid_password", "user_id": user.id}
            )
            return None
        
        # 更新最后登录时间
        user.last_login = datetime.now(timezone.utc)
        await self.user_repository.update(user.id, last_login=user.last_login)
        
        # 记录成功登录
        await self.audit_service.log_user_action(
            user_id=user.id,
            action="login_success",
            details={"login_time": user.last_login.isoformat()}
        )
        
        return user
    
    async def update_user(
        self,
        user_id: str,
        **kwargs
    ) -> Optional[User]:
        """更新用户信息"""
        user = await self.get_user_by_id(user_id)
        if not user:
            raise UserNotFoundException(user_id=user_id)
        
        # 验证更新的数据
        if "email" in kwargs:
            if not kwargs["email"] or "@" not in kwargs["email"]:
                raise ValueError("Invalid email format")
        if "username" in kwargs:
            if not kwargs["username"] or len(kwargs["username"]) < 3:
                raise ValueError("Username must be at least 3 characters")
        
        # 检查用户名冲突
        if "username" in kwargs and kwargs["username"] != user.username:
            if await self.user_repository.exists_by_username_exclude_id(kwargs["username"], user_id):
                raise UserAlreadyExistsException(
                    message=f"用户名 '{kwargs['username']}' 已存在",
                    identifier=kwargs["username"]
                )
        
        # 检查邮箱冲突
        if "email" in kwargs and kwargs["email"] != user.email:
            if await self.user_repository.exists_by_email_exclude_id(kwargs["email"], user_id):
                raise UserAlreadyExistsException(
                    message=f"邮箱 '{kwargs['email']}' 已被注册",
                    identifier=kwargs["email"]
                )
        
        # 更新用户
        updated_user = await self.user_repository.update(user_id, **kwargs)
        
        # 记录审计日志
        await self.audit_service.log_user_action(
            user_id=user_id,
            action="user_updated",
            details={"updated_fields": list(kwargs.keys())}
        )
        
        return updated_user
    
    async def update_password(
        self,
        email: str,
        new_password: str
    ) -> bool:
        """更新用户密码"""
        user = await self.get_user_by_email(email)
        if not user:
            return False
        
        # 验证新密码
        if not new_password or len(new_password) < 6:
            raise ValueError("Password must be at least 6 characters")
        
        hashed_password = self.password_manager.hash_password(new_password)
        await self.user_repository.update(user.id, password_hash=hashed_password)
        
        # 记录审计日志
        await self.audit_service.log_security_event(
            event_type="password_changed",
            details={"user_id": user.id, "email": email}
        )
        
        return True
    
    async def delete_user(self, user_id: str) -> bool:
        """删除用户"""
        user = await self.get_user_by_id(user_id)
        if not user:
            return False
        
        success = await self.user_repository.delete(user_id)
        
        if success:
            # 记录审计日志
            await self.audit_service.log_user_action(
                user_id=user_id,
                action="user_deleted",
                details={"username": user.username, "email": user.email}
            )
        
        return success
    
    async def list_users(
        self,
        skip: int = 0,
        limit: int = 20,
        search: Optional[str] = None
    ) -> Tuple[List[User], int]:
        """获取用户列表"""
        return await self.user_repository.list(skip=skip, limit=limit, search=search)
    
    async def activate_user(self, user_id: str) -> bool:
        """激活用户"""
        user = await self.update_user(user_id, is_active=True)
        if user:
            await self.audit_service.log_user_action(
                user_id=user_id,
                action="user_activated",
                details={"activated_at": datetime.now(timezone.utc).isoformat()}
            )
        return user is not None
    
    async def deactivate_user(self, user_id: str) -> bool:
        """停用用户"""
        user = await self.update_user(user_id, is_active=False)
        if user:
            await self.audit_service.log_user_action(
                user_id=user_id,
                action="user_deactivated",
                details={"deactivated_at": datetime.now(timezone.utc).isoformat()}
            )
        return user is not None
